import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.sql.*;

public class DTNNode {

	static final int connectionfactor = 100;


	private DTNListener server;
	private DTNConnector client;
	private String NodeID;

	private void Report(String message){
		System.out.println(NodeID + " - " +message);
	}

	public DTNNode(String NodeID, int listenPort, double threshold){
		this.NodeID = NodeID;
		MessageStatistics messages = new MessageStatistics();
		ConnectionList connections;
		DTNJDBCConnector conn = new DTNJDBCConnector();
		PreparedStatement query = conn.createConnection("SELECT NODE2_NAME, CONN_PROBABILITY FROM NODE_STATS WHERE NODE1_NAME = '" + NodeID + "'");
		try{
			ResultSet rs = query.executeQuery();
			connections = new ConnectionList(rs, connectionfactor);
			query.close();
		} catch (Exception e) {
			System.out.println(e.getMessage());
			connections = new ConnectionList();
		}

		query = conn.createConnection("SELECT SENDER_ID, RECEIVER_ID, MESSAGE_ID, TIME_TO_LIVE FROM MESSAGES WHERE SENDER_ID = '" + NodeID + "'");

		try{
			String source;
			String dest;
			int seq;
			int ttl;
			ResultSet rs = query.executeQuery();
			while (rs.next()){
				source = rs.getString("SENDER_ID");
				dest = rs.getString("RECEIVER_ID");
				seq = rs.getInt("MESSAGE_ID");
				ttl = rs.getInt("TIME_TO_LIVE");
				messages.AddMessage(source, dest, seq, ttl);
			}

			if (rs!=null)
				rs.close();
			if (query!=null);
			query.close();
			conn.release();
		} catch (Exception e) {
			//Report("Error adding message");
		}
		//messages.AddMessage(NodeID,"127.0.0.1:12340",10000,128);
		server = new DTNListener(NodeID, listenPort, messages, threshold);
		client =new DTNConnector(NodeID, connections, messages, threshold);
		Thread listener = new Thread(server);
		Thread connector = new Thread(client);
		listener.start();
		Report("DTNListener starting.");
		connector.start();
		Report("DTNConnector starting.");

	}

	public DTNNode(String NodeID, int listenPort, String partnerHost, int partnerPort, double threshold){
		this.NodeID = NodeID;
		MessageStatistics messages = new MessageStatistics();
		ConnectionList connections = new ConnectionList(partnerHost, partnerPort, connectionfactor);
		messages.AddMessage(NodeID,"127.0.0.1:" + partnerPort,10000,128);
		messages.AddMessage("A","B",partnerPort,128);

		server = new DTNListener(NodeID, listenPort, messages, threshold);
		client =new DTNConnector(NodeID, connections, messages, threshold);
		Thread listener = new Thread(server);
		Thread connector = new Thread(client);
		listener.start();
		Report("DTNListener starting.");
		connector.start();
		Report("DTNConnector starting.");
	}

	public void end(){
		server.close();
		Report("DTNListener shutting down.");
		client.close();
		Report("DTNConnector shutting down.");
	}

	public static void dumpTables(){
		DTNJDBCConnector conn;
		PreparedStatement query;
		ResultSet rs;
		String source;
		String dest;
		int seq;
		int ttl;
		double threshold;


		conn = new DTNJDBCConnector();
		query = conn.createConnection("SELECT * FROM DELIVERED_MESSAGE_RPT");
		String deliveredMessages = "SOURCE,DESTINATION,MESSAGE_ID,TIME_TO_LIVE,THRESHOLD\n";
		try{

			rs = query.executeQuery();
			while (rs.next()){
				source = rs.getString("SOURCE");
				dest = rs.getString("DESTINATION");
				seq = rs.getInt("MESSAGE_ID");
				ttl = rs.getInt("TIME_TO_LIVE");
				threshold = rs.getDouble("THRESHOLD");
				deliveredMessages = deliveredMessages + source + "," + dest + "," + seq + "," + ttl + "," + threshold + "\n";

			}

			if (rs!=null)
				rs.close();
			if (query!=null);
			query.close();
			conn.release();
			writeTextFile("./DeliveredMessages.csv", deliveredMessages);
		} catch (Exception e) {
			//Report("Error adding message");
		}


		conn = new DTNJDBCConnector();
		query = conn.createConnection("SELECT * FROM UNDELIVERED_MESSAGE_RPT");
		String undeliveredMessages = "SOURCE,DESTINATION,MESSAGE_ID,THRESHOLD\n";
		try{

			rs = query.executeQuery();
			while (rs.next()){
				source = rs.getString("SOURCE");
				dest = rs.getString("DESTINATION");
				seq = rs.getInt("MESSAGE_ID");
				threshold = rs.getDouble("THRESHOLD");
				undeliveredMessages = undeliveredMessages + source + "," + dest + "," + seq + "," + threshold + "\n";

			}

			if (rs!=null)
				rs.close();
			if (query!=null);
			query.close();
			conn.release();
			writeTextFile("./UndeliveredMessages.csv", undeliveredMessages);
		} catch (Exception e) {
			//Report("Error adding message");
		}

		conn = new DTNJDBCConnector();
		query = conn.createConnection("SELECT * FROM PROPAGATION_TYPE_RPT");
		String propagationType = "SOURCE,DESTINATION,TYPE,THRESHOLD\n";
		try{

			rs = query.executeQuery();
			while (rs.next()){
				source = rs.getString("NODE1");
				dest = rs.getString("NODE2");
				seq = rs.getInt("STAT_TYPE");
				threshold = rs.getDouble("THRESHOLD");
				propagationType = propagationType + source + "," + dest + "," + seq + "," + threshold + "\n";

			}

			if (rs!=null)
				rs.close();
			if (query!=null);
			query.close();
			conn.release();
			writeTextFile("./PropagationType.csv", propagationType);
		} catch (Exception e) {
			//Report("Error adding message");
		}
		
		conn = new DTNJDBCConnector();
		query = conn.createConnection("SELECT * FROM MESSAGE_BUFFER_RPT");
		String queueLength = "NODEID, MESSAGE_COUNT,THRESHOLD\n";
		try{

			rs = query.executeQuery();
			while (rs.next()){
				source = rs.getString("NODEID");
				seq = rs.getInt("MESSAGE_COUNT");
				threshold = rs.getDouble("THRESHOLD");
				//System.out.println(source + "," + seq + "," + threshold);
				queueLength = queueLength + source + "," + seq + "," + threshold + "\n";

			}

			if (rs!=null)
				rs.close();
			if (query!=null);
			query.close();
			conn.release();
			writeTextFile("./QueueLength.csv", queueLength);
		} catch (Exception e) {
			//Report("Error adding message");
		}

	}

	public static boolean writeTextFile(String filename, String message){
		try{
			File myFile = new File(filename);
			Writer output = new BufferedWriter(new FileWriter(myFile));
			output.write(message);
			output.close();
			return true;
		} catch (Exception e){
			System.out.println("Could not write to file " + filename);
			return false;
		}
	}

	//The main program class. This class should be used to launch threads and provide any interface elements
	public static void main(String[] args) {

		if (args.length != 1){
			System.out.println("Usage: DTNNode <Threshold 0.0 - 1.0>");
			System.exit(0);
		}
		double threshold = 0.0;
		try{
			threshold = Double.parseDouble(args[0]);
		} catch (Exception e){
			System.out.println("Usage: DTNNode <Threshold 0.0 - 1.0>");
			System.exit(0);
		}

		if (threshold < 0.0){
			threshold = 0.0;
		}

		if (threshold > 1.0){
			threshold = 1.0;
		}

		//dumpTables();

		DTNNode node0 = new DTNNode("127.0.0.1:12340",12340, threshold);
		DTNNode node1 = new DTNNode("127.0.0.1:12341",12341, threshold);
		DTNNode node2 = new DTNNode("127.0.0.1:12342",12342, threshold);
		DTNNode node3 = new DTNNode("127.0.0.1:12343",12343, threshold);
		DTNNode node4 = new DTNNode("127.0.0.1:12344",12344, threshold);
		DTNNode node5 = new DTNNode("127.0.0.1:12345",12345, threshold);
		DTNNode node6 = new DTNNode("127.0.0.1:12346",12346, threshold);
		DTNNode node7 = new DTNNode("127.0.0.1:12347",12347, threshold);
		DTNNode node8 = new DTNNode("127.0.0.1:12348",12348, threshold);
		DTNNode node9 = new DTNNode("127.0.0.1:12349",12349, threshold);
		DTNNode node10 = new DTNNode("127.0.0.1:12350",12350, threshold);
		DTNNode node11 = new DTNNode("127.0.0.1:12351",12351, threshold);
		DTNNode node12 = new DTNNode("127.0.0.1:12352",12352, threshold);
		DTNNode node13 = new DTNNode("127.0.0.1:12353",12353, threshold);
		DTNNode node14 = new DTNNode("127.0.0.1:12354",12354, threshold);
		DTNNode node15 = new DTNNode("127.0.0.1:12355",12355, threshold);
		DTNNode node16 = new DTNNode("127.0.0.1:12356",12356, threshold);
		DTNNode node17 = new DTNNode("127.0.0.1:12357",12357, threshold);
		DTNNode node18 = new DTNNode("127.0.0.1:12358",12358, threshold);
		DTNNode node19 = new DTNNode("127.0.0.1:12359",12359, threshold);

		try{
			Thread.sleep(1200000);
		} catch (Exception e){

		}
		node0.end();
		node1.end();
		node2.end();
		node3.end();
		node4.end();
		node5.end();
		node6.end();
		node7.end();
		node8.end();
		node9.end();
		node10.end();
		node11.end();
		node12.end();
		node13.end();
		node14.end();
		node15.end();
		node16.end();
		node17.end();
		node18.end();
		node19.end();
	
	}

}